﻿/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("SCS");

SCS.FlexibleDialogControl = function (element) {
    SCS.FlexibleDialogControl.initializeBase(this, [element]);

    /* Fields
    ****************************************************************************************************************/

    // delegates
    this._updatedDelegate = null;
    this._updatingDelegate = null;
    this._navigateDelegate = null;
    this._openDelegate = null;
    this._scriptsLoadedDelegate = null;
    this._requestCompleteDelegate = null;
    this._hidingDelegate = null;

    this._openerData = null;

    this._behaviors = [];
    this._contextData = {};
    this._contextKey = null;
    this._confirmClose = false;
    this._confirmCloseMsg = "Are you sure you want to close?";

    this._tempFlag;
};

SCS.FlexibleDialogControl.prototype = {

    /* Setup
    ****************************************************************************************************************/

    initialize: function () {

        SCS.FlexibleDialogControl.callBaseMethod(this, 'initialize');

        if (typeof (jQuery) == "undefined")
            throw new Error("JQuery is not available. Ensure jQuery has been added to the ScriptManager.");

        this._updatedDelegate = Function.createDelegate(this, this._onUpdated);
        this.add_Updated(this._updatedDelegate);

        this._updatingDelegate = Function.createDelegate(this, this._onUpdating);
        this.add_Updating(this._updatingDelegate);

        this._hidingDelegate = Function.createDelegate(this, this._onHidding);
        this.add_Hiding(this._hidingDelegate);

        this._wireOpenElements();

        this._requestCompleteDelegate = Function.createDelegate(this, this._onRequestComplete);
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._requestCompleteDelegate);
    },

    /* Teardown
    ****************************************************************************************************************/

    dispose: function () {

        this.remove_Updated(this._updatedDelegate);
        this._updatedDelegate = null;

        this.remove_Updating(this._updatingDelegate);
        this._updatingDelegate = null;

        this.add_Hiding(this._hidingDelegate);
        this._hidingDelegate = null;

        Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._requestCompleteDelegate);
        this._requestCompleteDelegate = null;

        this._unwireOpenElements();

        this._disposeContent();

        SCS.FlexibleDialogControl.callBaseMethod(this, 'dispose');
    },

    /* Event Handlers
    ****************************************************************************************************************/

    _onUpdating: function () {

        this._disposeContent();
    },

    _onUpdated: function (sender, args) {

        this._updateContent();

        this.get_ModalPopupBehavior()._layout();
    },

    _onNavigate: function (e) {

        var dataAttribute = e.target.getAttribute("dialog-action");

        if (dataAttribute) {

            var data;
            eval("data = " + dataAttribute);

            if (typeof (data.defer) == "undefined" || !data.defer) {
                this._holdPosition = true;
                this.populate(data);
            }
        }
    },

    _onOpen: function (e) {

        var dataAttribute = e.target.getAttribute("dialog-open");

        if (dataAttribute) {

            eval("this._openerData = " + dataAttribute);

            this.setContentSettings(this._openerData);
            this.show();
        }
    },

    _onRequestComplete: function (sender, args) {

        this._unwireOpenElements();
        this._wireOpenElements();
    },

    _onHidding: function (sender, args) {

        if (this._confirmClose) {
            args.set_cancel(true);

            this.showMessage(this._confirmCloseMsg, "warn", ["Yes", "No"], $.proxy(function (e) {

                if ($(e.target).attr("value") == "Yes") {
                    this._confirmClose = false;
                    this.hide();
                }

            }, this));
        }
    },

    /* Public Methods
    ****************************************************************************************************************/

    show: function (caption) {

        this._holdPosition = false;
        SCS.FlexibleDialogControl.callBaseMethod(this, 'show', [caption, undefined]);
    },

    showMessage: function (message, messageType, buttonNames, buttonCallback) {

        var root = $(this.get_element()),
            controlId = "flexMsgBox",
            control = $("#" + controlId, root);

        if (control)
            this.hideMessage();

        $(root).append(String.format(
            "<div style='position:absolute;display:none;' class='msgbox msgbox-{0}' id='{1}'></div>",
                messageType, controlId));

        control = $("#" + controlId, root);

        if (typeof (className) != "undefined")
            control.attr("class", className);

        var html = message;

        if (typeof (buttonNames) != "undefined") {

            html += "<div class='buttons'>";

            for (var i = 0; i < buttonNames.length; i++)
                html += String.format("<input type='button' value='{0}'/>", buttonNames[i]);

            html += "</div>";

            control.html(html);

            var buttons = control.find("input:button");

            buttons.click($.proxy(function (e) {

                if (buttonCallback && typeof (buttonCallback) === "function")
                    buttonCallback(e);

                control.hide();

            }, this));
        }
        else {
            control.html(html);
        }

        var top = root.height() / 2 - control.height() / 2,
            left = root.width() / 2 - control.width() / 2;

        control.css("top", top - 20).css("left", left - 20).show();
    },

    hideMessage: function () {

        control = $("#flexMsgBox", this.get_element());
        control.find("input:button").unbind("click");
        control.remove();
    },

    getContentData: function (pageIndex) {

        var key = this._contextKey.split("#")[0] + "#" + pageIndex;

        return this._contextData[key];
    },

    clearContentData: function () {

        if (this._contextKey) {

            var keyParts = this._contextKey.split("#");

            if (keyParts.length > 1)

                for (var item in this._contextData) {
                    if (item.startsWith(keyParts[0] + "#"))
                        this._contextData[item] = null;
                }
            else
                this._contextData[keyParts[0]] = null;
        }
    },

    /* Private Methods
    ****************************************************************************************************************/

    _getNavElements: function () {

        return $("*[dialog-action]", this.get_ContentElement());
    },
    _wireNavElements: function () {

        //Sys.Debug.fail("");

        this._navigateDelegate = Function.createDelegate(this, this._onNavigate);

        this._getNavElements().bind("click.flexNav", this._navigateDelegate).filter("a").attr("href", "javascript:{}");
    },

    _unwireNavElements: function () {

        this._getNavElements().unbind("click.flexNav");
    },

    _getOpenElements: function () {

        return $("*[dialog-open]");
    },
    _wireOpenElements: function () {

        this._openDelegate = Function.createDelegate(this, this._onOpen);

        this._getOpenElements().bind("click.openFlexNav", this._openDelegate).filter("a").attr("href", "javascript:{}");
    },

    _unwireOpenElements: function () {

        this._getOpenElements().unbind("click.openFlexNav");
    },

    _saveContextData: function () {

        if (this._contextKey) {

            var data = {},
                formElements = $("input:hidden,input:text,select,textarea", this.get_ContentElement());

            Array.forEach(formElements.toArray(), function (element) {
                var element = $(element);

                data[element.attr("id")] = element.val().replace("'", "\'");

            }, this);

            this._contextData[this._contextKey] = data;
        }
    },

    _loadContextData: function () {

        if (this._contextKey && typeof (this._contextData[this._contextKey]) != "undefined") {

            for (var item in this._contextData[this._contextKey]) {
                $("#" + item, this.get_ContentElement()).val(this._contextData[this._contextKey][item]);
            }
        }
    },

    _updateContent: function () {

        //Sys.Debug.fail("");

        if (typeof (Sys.loader) == "undefined")
            throw new Error("Sys.loader is not available. Ensure the start.js file has been added to the ScriptManager.");

        //Sys.Debug.fail("");

        // add event handlers to navigation elements
        this._wireNavElements();

        // update main dialog properties
        //
        var dataElem = $("div[dialog-data]", this._contentControl);

        if (dataElem.length > 0) {

            var data;
            eval("data = " + dataElem.attr("dialog-data"));

            // update dialog css class
            if (typeof (data.className) != "undefined")
                $(this.get_element()).get(0).className = data.className;

            // update dialog title
            if (typeof (data.caption) != "undefined")
                this.set_Caption(data.caption);

            // add css file if not already present
            if (typeof (data.styleUrl) != "undefined")
                this._attachStylesheet(data.styleUrl);
        }

        // write dialog-host attribute to sub form so child scripts can call this behavior easily        
        $("div", this._contentControl).attr("dialog-host", String.format("{{'behaviorId':'{0}'}}", this.get_id()))

        // reload form field data
        this._loadContextData();

        // Build array of required behavior names for Sys.require.
        // These names must match the behavior names in the ScriptDefinitions.js file        
        // Note: the "type" and "name" properties are required for each behavior.

        var behaviorDef = this._getBehaviorDef(),
            behaviorNames = [];

        if (behaviorDef) {
            Array.forEach(behaviorDef, function (behavior) {

                if (typeof (behavior.name) == "undefined")
                    throw new Error("The behavior name property is missing.");

                Array.add(behaviorNames, behavior.name);

            }, this);

            Sys.require(behaviorNames, Function.createDelegate(this, this._onScriptsReady));
        }
    },

    _attachStylesheet: function (url) {

        //Sys.Debug.fail("");

        var found = false;

        url = url.toLowerCase();

        $("head link[type='text/css']").each(function () {

            if ($(this).attr("href").toLowerCase() == url)
                found = true;
        });

        if (!found)
            $("head").append(String.format("<link type='text/css' rel='stylesheet' href='{0}'/>", url));
    },

    _getBehaviorDef: function () {

        var behaviorNodes = $("div[dialog-behaviors]", this.get_ContentElement()),
            behaviors = null;

        if (behaviorNodes.length > 0)
            eval("behaviors = " + behaviorNodes.attr("dialog-behaviors"));

        return behaviors;
    },

    _onScriptsReady: function () {

        //Sys.Debug.fail("");

        // load behaviors
        //
        var behaviorDef = this._getBehaviorDef();

        if (behaviorDef.length > 0) {

            Array.forEach(behaviorDef, function (behavior) {

                // set defaults to simplify markup
                if (typeof (behavior.properties) == "undefined") behavior.properties = [];
                if (typeof (behavior.events) == "undefined") behavior.events = [];
                if (typeof (behavior.references) == "undefined") behavior.references = [];

                var behaviorElem;

                if (typeof (behavior.elementId) == "undefined")
                    behaviorElem = $("div", this.get_ContentElement()).get(0); // default to first div in content area
                else
                    behaviorElem = $get(behavior.elementId);

                if (typeof (behavior.properties.id) == "undefined") {

                    // create default behavior id
                    behavior.properties.id = behavior.name + "Handle";
                }

                var behaviorInstance = $create(behavior.type, behavior.properties, behavior.events, behavior.references, behaviorElem);

                // set properties
                //
                if (typeof (this._openerData.properties) != "undefined") {

                    var props = this._openerData.properties;

                    for (var item in props) {

                        var funcStr = "behaviorInstance.set_" + item,
                            func;

                        eval("func = " + funcStr);

                        if (typeof (func) == "function") {

                            var param = props[item];

                            if (typeof (param) == "string") {

                                param = param.replace(/'/g, '"');
                                param = "'" + param + "'";
                            }

                            eval(funcStr + "(" + param + ")");
                        }
                    }
                }

                // wire events
                //

                if (typeof (this._openerData.events) != "undefined") {

                    var events = this._openerData.events;

                    for (var item in events) {

                        var funcStr = "behaviorInstance.add_" + item,
                            func;

                        eval("func = " + funcStr);

                        if (typeof (func) == "function") {

                            var event = events[item];

                            if (typeof (event) == "function") {

                                eval(funcStr + "(" + event + ")");
                            }
                        }
                    }
                }

                Array.add(this._behaviors, behaviorInstance);

            }, this);
        }
    },

    _disposeContent: function () {

        this._unwireNavElements();
        this._saveContextData();

        Array.forEach(this._behaviors, function (behavior) {

            Sys.Application.removeComponent(behavior);
            behavior.dispose();
            behavior = null;
        });

        Array.clear(this._behaviors);
    },

    onRepositioning: function (sender, args) {

        if (typeof (this._holdPosition) != "undefined")
            args.set_cancel(this._holdPosition);
    },

    get_ConfirmClosing: function () {

        return this._confirmClose;
    },
    set_ConfirmClosing: function (value) {

        this._confirmClose = value;
    },
    get_ClosingMessage: function () {

        return this._confirmCloseMsg;
    },
    set_ClosingMessage: function (value) {

        this._confirmCloseMsg = value;
    }

    /* Properties
    ****************************************************************************************************************/
};

/* Registration
****************************************************************************************************************/

SCS.FlexibleDialogControl.registerClass('SCS.FlexibleDialogControl', SCS.DialogControl);

